package dc.com.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;

import javax.sql.DataSource;

import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;

import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.fastjson.JSONObject;

import dc.com.constant.Const;

/**
 * 
 * <B>系统名称：</B>通用系统功能<BR>
 * <B>模块名称：</B>数据访问通用功能<BR>
 * <B>中文类名：</B>基础数据访问<BR>
 * <B>概要说明：</B><BR>
 * @author zhangl（D）
 * @since 2017年8月2日
 */
public class BaseJdbcDao {
	//Json数据映射器
	private static final JsonRowMapper JSON_ROW_MAPPER = new JsonRowMapper();
	
	//jdbc调用模版
	private JdbcTemplate jdbcTemplate;
	
	//启动时间
	private static Date startTime;
	
	/**
     * <B>方法名称：</B>初始化JDBC调用模板<BR>
     * <B>概要说明：</B><BR>
     * 
     * @param dataSource 数据源
     */
	@Autowired
	public void initJdbcTemplate(DataSource ds) {
		this.jdbcTemplate = new JdbcTemplate(ds);
		if(startTime == null) {
			startTime = getCurrentTime();
		}
	}
	
	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}
	
	 /**
     * 
     * <B>方法名称：</B>获取数据库的当前时间<BR>
     * <B>概要说明：</B><BR>
     * 
     * @return Date 当前时间
     */
	public Date getCurrentTime() {
		return this.getJdbcTemplate().queryForObject("SELECT SYSTIMESTAMP FROM DUAL",Date.class);
	}
	
	public Date getStartTime() {
		return startTime;
	}
	 
	public List<JSONObject> queryForJsonList(String sql, Object...args) {
		return this.jdbcTemplate.query(sql, JSON_ROW_MAPPER, args);
	}
	
	public JSONObject queryForJsonObject(String sql, Object...args) {
		List<JSONObject> jsonList = this.jdbcTemplate.query(sql, JSON_ROW_MAPPER, args);
		if(jsonList == null || jsonList.size() < 1) {
			return null;
		}
		return jsonList.get(0);
	}
	
	public String queryForString(String sql, Object...args) {
		List<String> stringList = this.jdbcTemplate.queryForList(sql,args,String.class);
		if(stringList == null || stringList.size() < 1) {
			return null;
		}
		return stringList.get(0);
	}
	
	/**
     * <B>方法名称：</B>拼接分页语句<BR>
     * <B>概要说明：</B><BR>
     * 
     * @param sql SQL语句
     * @param start 开始记录行数（0开始）
     * @param limit 每页限制记录数
     */
	public void appendPageSql(StringBuffer sql, int start, int limit) {
		sql.insert(0, "SELECT * FROM (SELECT PAGE_VIEW.*, ROWNUM AS ROW_SEQ_NO FROM (");
		sql.append(") PAGE_VIEW WHERE ROWNUM <= " + (start + limit) + ") WHERE ROW_SEQ_NO > " + start);
	}
	
	public void appendOrgSubQuerySql(StringBuffer sql, List<Object> params, String orgId) {
		sql.append("SELECT ORG_ID FROM MST_ORG_REF WHERE PARENT_ID = ?");
		params.add(orgId);
	}
	
	/**
     * <B>方法名称：</B>获取唯一键值<BR>
     * <B>概要说明：</B><BR>
     * @return String 唯一键值
     */
	public String generateKey() {
		String sql = "SELECT '0000' || TO_CHAR(SYSTIMESTAMP,'YYYYMMDD') FROM DUAL ";
		String pre = this.jdbcTemplate.queryForObject(sql, String.class);
		String uid = UUID.randomUUID().toString().replace("-", "").toUpperCase();
		return pre + uid.substring(12); 
		
	}
	

    /**
     * <B>方法名称：</B>用于 in 通配符(?) 的拼接<BR>
     * <B>概要说明：</B>字段 in(?,?,?,?,?)<BR>
     * 
     * @param sql sql
     * @param sqlArgs 参数容器
     * @param params 参数的个数
     */
	public void appendSqlIn(StringBuffer sql, List<Object> sqlArgs, String[] params) {
		if(params !=null && params.length > 0) {
			sql.append(" (");
			for(int i = 0; i < params.length; i++) {
				if(i == 0) {
					sql.append("?");
				} else {
					sql.append(",?");
				}
				sqlArgs.add(params[i]);
			}
			sql.append(") ");
		}
	}
	
	/**
     * <B>方法名称：</B>适应SQL列名<BR>
     * <B>概要说明：</B><BR>
     * 
     * @param c 原列名
     * @return String 调整后列名
     */
	public static String c(String c) {
		if(StringUtils.isBlank(c)) {
			return null;
		}
		return c.trim().toUpperCase();
	}
	
	 /**
     * <B>方法名称：</B>适应SQL参数<BR>
     * <B>概要说明：</B>防止SQL注入问题<BR>
     * 
     * @param v 参数
     * @return String 调整后参数
     */
	public static String v(String v) {
		if(StringUtils.isBlank(v)) {
			return null;
		}
		return v.trim().replace("'", "''");
	}
	
	 /**
     * <B>方法名称：</B>获取日期文本值<BR>
     * <B>概要说明：</B><BR>
     * 
     * @param rs 结果集
     * @param column 列名
     * @return String 文本值
     * @throws SQLException SQL异常错误
     */
	protected String getDate(ResultSet rs, String cloumn) throws SQLException {
		Date date = rs.getDate(cloumn);
		if(date == null) {
			return null;
		}
		return DateFormatUtils.format(date, Const.FORMAT_DATE);
	}
	
	protected String getDateTime(ResultSet rs, String cloumn) throws SQLException {
		Date date = rs.getDate(cloumn);
		if(date == null) {
			return null;
		}
		return DateFormatUtils.format(date, Const.FORMAT_DATETIME);
	}
	
	protected String getDateTimestamp(ResultSet rs, String cloumn) throws SQLException {
		Date date = rs.getDate(cloumn);
		if(date == null) {
			return null;
		}
		return DateFormatUtils.format(date, Const.FORMAT_TIMESTAMP);
	}
	
	/**
     * <B>方法名称：</B>单表INSERT方法<BR>
     * <B>概要说明：</B>单表INSERT方法<BR>
     * @param tableName 表名
     * @param data JSONObject对象
     */
	protected int insert(String tableName, JSONObject data) {
		if(data.size() <= 0) {
			return 0;
		}
		StringBuffer sql = new StringBuffer(" INSERT INTO " + tableName + " ( ");
		
		Set<Entry<String, Object>> set = data.entrySet();
 		List<Object> sqlArgs = new ArrayList<Object>();
 		for(Iterator<Entry<String,Object>> iterator = set.iterator(); iterator.hasNext();) {
 			Entry<String,Object> entry = iterator.next();
 			sql.append(entry.getKey() + ",");
 			sqlArgs.add(entry.getValue());
 		}
 		
 		sql.delete(sql.length() - 1, sql.length());
 		sql.append(" ) VALUES ( ");
 		for(int i = 0; i<set.size(); i++) {
 			sql.append("?,");
 		}
 		sql.delete(sql.length() - 1, sql.length());
 		sql.append(" )");
		return this.jdbcTemplate.update(sql.toString(), sqlArgs.toArray());
	}
	
	/**
     * <B>方法名称：</B>批量新增數據方法<BR>
     * <B>概要说明：</B><BR>
     * @param tableName 数据库表名称
     * @param list 插入数据集合
     */
	protected void insertBach(String tableName, final List<LinkedHashMap<String,Object>> list) {
		if(list.size() <= 0) {
			return;
		}
		
		LinkedHashMap<String, Object> linkedHashMap = list.get(0);
		StringBuffer sql = new StringBuffer(" INSERT INTO ");
		sql.append(tableName + " ( ");
		
		final String[] keyset = (String[])linkedHashMap.keySet().toArray();
		for(int i = 0; i < linkedHashMap.size(); i++) {
			sql.append(keyset[i] + ", ");
		}
		
		sql.delete(sql.length() - 1, sql.length());
		sql.append(") VALUES (");
		for(int i = 0; i < linkedHashMap.size(); i++) {
			sql.append("?,");
		}
		sql.delete(sql.length() - 1, sql.length());
		sql.append(" ) ");
		
		this.jdbcTemplate.batchUpdate(sql.toString(), new BatchPreparedStatementSetter() {
			
			@Override
			public void setValues(PreparedStatement ps, int i) throws SQLException {
				LinkedHashMap<String,Object> map = list.get(i);
				Object[] values = map.values().toArray();
				for(int j = 0; j < values.length; j++) {
					ps.setObject(j + 1, values[j]);
				}
			}
			
			@Override
			public int getBatchSize() {
				
				return list.size();
			}
		});
	}
}

